pub mod connection;
pub mod handler;

use crate::config::Config;
use crate::storage::Storage;
use std::sync::Arc;
use tokio::net::TcpListener;
use tracing::{info, error};

pub use connection::*;
pub use handler::*;

/// Redis server
pub struct Server {
    storage: Arc<Storage>,
    config: Config,
}

impl Server {
    /// Create a new server instance
    pub fn new(storage: Arc<Storage>, config: Config) -> Self {
        Self { storage, config }
    }

    /// Start the server
    pub async fn start(&self, addr: &str) -> Result<(), Box<dyn std::error::Error>> {
        let listener = TcpListener::bind(addr).await?;
        info!("Minidis server listening on {}", addr);

        loop {
            match listener.accept().await {
                Ok((socket, peer_addr)) => {
                    info!("New client connected from {}", peer_addr);

                    let storage = self.storage.clone();
                    let config = self.config.clone();

                    tokio::spawn(async move {
                        let mut connection = Connection::new(socket, storage);

                        if let Err(e) = connection.handle().await {
                            error!("Connection error: {}", e);
                        }

                        info!("Client {} disconnected", peer_addr);
                    });
                }
                Err(e) => {
                    error!("Failed to accept connection: {}", e);
                }
            }
        }
    }
}